Next: 2 User Input and Up: OpenGL and X Previous: OpenGL and X

1 A Short GLUT Example


#include <GL/glut.h>

GLfloat light_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
GLUquadricObj *qobj;

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glCallList(1); /* render sphere display list */
    glutSwapBuffers();
}

void gfxinit(void)
{
    qobj = gluNewQuadric();
    gluQuadricDrawStyle(qobj, GLU_FILL);
    glNewList(1, GL_COMPILE); /* create sphere display list */
    gluSphere(qobj, /* radius */ 1.0, /* slices */ 20, /* stacks */ 20);
    glEndList();
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    gluPerspective( /* field of view in degree */ 40.0, /* aspect ratio */ 1.0,
                    /* Z near */ 1.0, /* Z far */ 10.0);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.0, 0.0, 5.0,   /* eye is at (0,0,5) */
              0.0, 0.0, 0.0,   /* center is at (0,0,0) */
              0.0, 1.0, 0.);   /* up is in positive Y direction */
    glTranslatef(0.0, 0.0, -1.0); 
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("sphere");
    glShadeModel(GL_FLAT);
    glutDisplayFunc(display);
    gfxinit();
    glutMainLoop();
}
Figure 1: Program using GLUT to render a lighted sphere using OpenGL. The GLUT specific lines are in bold; notice that very little GLUT-code is required.

Figure 1 is a simple GLUT program that draws a lighted sphere. The program merely renders the sphere when the window needs redrawing. But the example demonstrates the basics of opening a window with GLUT and rendering an image into it.

Briefly, I'll explain each GLUT call in the example.


    glutInit(&argc, argv);
This routine initializes GLUT. Most importantly, it processes any command line arguments GLUT understands (for X, this would be options like -display and -geometry). Any command line arguments recognized by GLUT are stripped out, leaving the remaining options for your program to process. Every GLUT program should call glutInit before any other GLUT routine.


    glutInitDisplayMode(GLUT_DOUBLE |
        GLUT_RGB | GLUT_DEPTH);
When a window is created, its type is determined by GLUT's current display mode. The display mode is a set of indicators that determine the frame buffer capabilities of the window. The call to glutInitDisplayMode means a subsequently created window should be created with the following capabilities: Other indicators like GLUT_STENCIL could be combined into the display mode value to request additional capabilities like a stencil buffer.


    glutCreateWindow("sphere");
Create a window for OpenGL rendering named ``sphere.'' If a connection to the X server hasn't yet been made, glutCreateWindow will do so and make sure that OpenGL is supported by the X server. Details such as picking the correct visual and colormap and communicating information like the window name to the window manager are handled by GLUT. Along with the window, an associated OpenGL rendering context is created. This means each window has its own private set of OpenGL state.

While this example doesn't use it, glutCreateWindow actually returns an integer identifier for the window. For an application with multiple windows, this lets you control multiple windows. Because of GLUT's design, you will rarely need a window's identifier. This is because GLUT keeps a current window as part of its state. Most window operations implicitly affect the current window. When a window is created, the current window is implicitly set to the new window.

For example:


    glutDisplayFunc(display);
will register the display function as the routine to be called when the current (and just created) window needs to be drawn.

Also notice that OpenGL routines that initialize OpenGL's state in gfxinit() implicitly affect the OpenGL context for the current window.

If you do need to change the current window, you can call glutSetWindow(winnum), where winnum is a window identifier. You can also call glutGetWindow() that returns the current window identifier.

Whenever a callback is made for a specific window, the current window is implicitly set to the window prompting the callback. So when the display callback registered with glutDisplayFunc is called, we know that GLUT has implicitly changed the current window to the window that needs to be redisplayed. This means display can call OpenGL rendering routines and the routines will affect the correct window.


    glutMainLoop();
This routine serves the same purpose as the X Toolkit's XtAppMainLoop routine; it begins event processing and maps any windows that have been created. It never exits. Callback functions registered with GLUT are called as necessary. For example, the display routine in the example will be called whenever Expose events are received by the program from the X server.


    glutSwapBuffers();
When we created the window, the display mode was set to request a double buffered window. After display renders the sphere using OpenGL routines, glutSwapBuffers is called to swap the current window's buffers to make the image rendered into the back buffer visible. So the sphere is displayed without the program's user seeing the rendering in progress.

Supporting more than one window is easy. To create a second window with the same red sphere add the following calls before glutMainLoop:


    glutCreateWindow("a second window");
    glutDisplayFunc(display);
    gfxinit();
Because of the implicit update of the current window, display will also be registered for the second window and gfxinit will initialize the second window's OpenGL context. And remember that when a callback like display is called, the current window is implicitly set to the window needing the callback, so the rendering done by display will be directed into the correct window. The result of the output of the resulting program can be seen in Figure 2.

Figure 2: The two windows generated by the modified version of code in Figure 1.



Next: 2 User Input and Up: OpenGL and X Previous: OpenGL and X


mjk@asd.sgi.com
Thu Oct 27 23:21:28 PDT 1994